/**
 * 输入验证模式 - 使用 Zod 进行严格的类型验证
 * 
 * 防止 XSS、注入攻击和数据格式错误
 */

import { z } from 'zod'

// 基础验证规则
const sanitizeString = (str: string) => {
  // 移除潜在的 XSS 字符
  return str
    .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
    .replace(/<[^>]*>/g, '')
    .trim()
}

// 基础字符串验证器
const baseString = (minLength = 1, maxLength = 1000) =>
  z.string()
    .min(minLength, `最少需要 ${minLength} 个字符`)
    .max(maxLength, `最多允许 ${maxLength} 个字符`)

// 清理后的字符串验证器
const sanitizedString = (minLength = 1, maxLength = 1000) =>
  baseString(minLength, maxLength)
    .transform(sanitizeString)
    .refine(val => val.length >= minLength, `清理后内容不能少于 ${minLength} 个字符`)

// 用户名验证器
const usernameString = baseString(2, 50)
  .regex(/^[a-zA-Z0-9\u4e00-\u9fa5_-]+$/, '用户名只能包含字母、数字、中文、下划线和连字符')
  .transform(sanitizeString)

// URL 验证
const urlSchema = z.string()
  .url('请输入有效的URL')
  .refine(url => {
    try {
      const parsed = new URL(url)
      return ['http:', 'https:'].includes(parsed.protocol)
    } catch {
      return false
    }
  }, '只允许 HTTP 和 HTTPS 协议')

// 可选的图片 URL 验证 (允许空字符串)
const optionalImageUrlSchema = z.string().optional().refine((val) => {
  if (!val || val === '') return true // 允许空值
  try {
    const parsed = new URL(val)
    return ['http:', 'https:'].includes(parsed.protocol)
  } catch {
    return false
  }
}, '请输入有效的图片URL或留空')

// 灵活的网站地址验证 (支持多种格式)
const flexibleWebsiteSchema = z.string().optional().refine((val) => {
  if (!val || val === '') return true // 允许空值

  // 如果已经是完整URL，验证协议
  if (val.includes('://')) {
    try {
      const parsed = new URL(val)
      return ['http:', 'https:'].includes(parsed.protocol)
    } catch {
      return false
    }
  }

  // 更宽松的域名格式验证
  // 支持: example.com, www.example.com, subdomain.example.com, example.com/path, example.co.uk
  const domainRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*\.[a-zA-Z]{2,}(\/.*)?$/
  return domainRegex.test(val)
}, '请输入有效的网站地址')

// 邮箱验证
const emailSchema = z.string()
  .email('请输入有效的邮箱地址')
  .max(254, '邮箱地址过长')
  .transform(email => email.toLowerCase().trim())

// 用户相关验证
export const userValidation = {
  // 用户注册
  register: z.object({
    email: emailSchema,
    password: z.string()
      .min(8, '密码至少需要8个字符')
      .max(128, '密码不能超过128个字符')
      .regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/, '密码必须包含大小写字母和数字'),
    name: usernameString,
    confirmPassword: z.string()
  }).refine(data => data.password === data.confirmPassword, {
    message: '两次输入的密码不一致',
    path: ['confirmPassword']
  }),

  // 用户登录
  login: z.object({
    email: emailSchema,
    password: z.string().min(1, '请输入密码')
  }),

  // 更新用户资料
  updateProfile: z.object({
    name: sanitizedString(2, 50).optional(), // 姓名也应该是可选的
    email: emailSchema.optional(), // 邮箱在更新时应该是可选的
    avatar: urlSchema.optional(),
    bio: sanitizedString(0, 200).optional(),
    website: flexibleWebsiteSchema // 使用灵活的网站地址验证
  })
}

// 工具相关验证
export const toolValidation = {
  // 创建工具
  create: z.object({
    title: sanitizedString(2, 100),
    description: sanitizedString(10, 1000),
    url: urlSchema,
    image: optionalImageUrlSchema, // 使用新的可选图片URL验证
    categoryId: z.string().min(1, '分类ID不能为空'),
    tags: z.array(sanitizedString(1, 20)).max(10, '最多允许10个标签').optional()
  }),

  // 更新工具
  update: z.object({
    title: sanitizedString(2, 100).optional(),
    description: sanitizedString(10, 1000).optional(),
    url: urlSchema.optional(),
    image: optionalImageUrlSchema, // 使用新的可选图片URL验证
    categoryId: z.string().min(1, '分类ID不能为空').optional(),
    status: z.enum(['PENDING', 'APPROVED', 'REJECTED']).optional(),
    isDeployed: z.boolean().optional(),
    deployPath: z.string().max(200).optional(),
    tags: z.array(sanitizedString(1, 20)).max(10, '最多允许10个标签').optional()
  }),

  // 搜索工具
  search: z.object({
    q: sanitizedString(0, 100).optional(),
    category: z.string().min(1).optional(), // 改为普通字符串，因为分类ID可能不是UUID
    status: z.enum(['PENDING', 'APPROVED', 'REJECTED']).optional(),
    page: z.coerce.number().int().min(1).max(1000).default(1),
    limit: z.coerce.number().int().min(1).max(100).default(20),
    sortBy: z.enum(['createdAt', 'updatedAt', 'title', 'rating']).default('createdAt'),
    sortOrder: z.enum(['asc', 'desc']).default('desc')
  })
}

// 评价相关验证
export const reviewValidation = {
  // 创建评价
  create: z.object({
    rating: z.number()
      .int('评分必须是整数')
      .min(1, '评分不能低于1')
      .max(5, '评分不能高于5'),
    comment: sanitizedString(5, 500)
  }),

  // 更新评价
  update: z.object({
    rating: z.number()
      .int('评分必须是整数')
      .min(1, '评分不能低于1')
      .max(5, '评分不能高于5')
      .optional(),
    comment: sanitizedString(5, 500).optional()
  })
}

// 分类相关验证
export const categoryValidation = {
  // 创建分类
  create: z.object({
    name: sanitizedString(2, 50),
    description: sanitizedString(0, 200).optional(),
    icon: z.string().max(10, '图标字符过长').optional()
  }),

  // 更新分类
  update: z.object({
    name: sanitizedString(2, 50).optional(),
    description: sanitizedString(0, 200).optional(),
    icon: z.string().max(10, '图标字符过长').optional()
  })
}

// 收藏相关验证
export const favoriteValidation = {
  // 添加收藏
  create: z.object({
    toolId: z.string().min(1, '工具ID不能为空')
  })
}

// 文件上传验证
export const fileValidation = {
  // 工具文件上传
  toolUpload: z.object({
    file: z.any()
      .refine(file => file instanceof File, '必须是有效的文件')
      .refine(file => file.size <= 10 * 1024 * 1024, '文件大小不能超过10MB')
      .refine(
        file => ['application/zip', 'text/html', 'application/x-zip-compressed'].includes(file.type),
        '只支持 ZIP 和 HTML 文件'
      ),
    title: sanitizedString(2, 100),
    description: sanitizedString(10, 1000),
    categoryId: z.string().min(1, '分类ID不能为空')
  })
}

// 管理员相关验证
export const adminValidation = {
  // 工具审核
  reviewTool: z.object({
    status: z.enum(['APPROVED', 'REJECTED']),
    reason: sanitizedString(0, 500).optional()
  }),

  // 用户管理
  updateUser: z.object({
    role: z.enum(['USER', 'ADMIN']).optional(),
    status: z.enum(['ACTIVE', 'SUSPENDED', 'BANNED']).optional(),
    reason: sanitizedString(0, 500).optional()
  })
}

// 通用验证函数
export function validateInput<T>(schema: z.ZodSchema<T>, data: unknown): {
  success: boolean
  data?: T
  errors?: string[]
} {
  try {
    const result = schema.parse(data)
    return { success: true, data: result }
  } catch (error) {
    console.error('Validation error:', error)

    if (error instanceof z.ZodError) {
      const errors = (error.errors || []).map(err =>
        `${(err.path || []).join('.')}: ${err.message || '验证失败'}`
      )
      return { success: false, errors: errors.length > 0 ? errors : ['验证失败'] }
    }

    return { success: false, errors: [error instanceof Error ? error.message : '验证失败'] }
  }
}

// 中间件验证函数
export function createValidationMiddleware<T>(schema: z.ZodSchema<T>) {
  return (data: unknown) => {
    const result = validateInput(schema, data)
    if (!result.success) {
      throw new Error(`验证失败: ${result.errors?.join(', ')}`)
    }
    return result.data!
  }
}

// 批量验证
export function validateBatch<T>(
  schema: z.ZodSchema<T>, 
  dataArray: unknown[]
): {
  success: boolean
  data?: T[]
  errors?: { index: number; errors: string[] }[]
} {
  const results: T[] = []
  const errors: { index: number; errors: string[] }[] = []

  dataArray.forEach((data, index) => {
    const result = validateInput(schema, data)
    if (result.success) {
      results.push(result.data!)
    } else {
      errors.push({ index, errors: result.errors! })
    }
  })

  if (errors.length > 0) {
    return { success: false, errors }
  }

  return { success: true, data: results }
}

// 导出常用的验证器
export const validators = {
  email: emailSchema,
  url: urlSchema,
  sanitizedString,
  uuid: z.string().uuid(),
  positiveInt: z.number().int().positive(),
  nonNegativeInt: z.number().int().min(0)
}
